package com.hxzon.aixzsecretary.ui;

/*
 * hxzon,AixzCalendar
 * */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DecimalFormat;
import java.util.Calendar;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;

import com.hxzon.aixzsecretary.util.AixzObservable;
import com.hxzon.aixzsecretary.util.AixzSensor;

public class AixzCalendar extends JPanel implements AixzObservable {

	public static final String WEEK_SUN = "SUN";
	public static final String WEEK_MON = "MON";
	public static final String WEEK_TUE = "TUE";
	public static final String WEEK_WED = "WED";
	public static final String WEEK_THU = "THU";
	public static final String WEEK_FRI = "FRI";
	public static final String WEEK_SAT = "SAT";

	public static final Color background = Color.white;
	public static final Color foreground = Color.black;
	public static final Color headerBackground = Color.blue;
	public static final Color headerForeground = Color.white;
	public static final Color selectedBackground = Color.blue;
	public static final Color selectedForeground = Color.white;

	private JPanel cPane;
	private JLabel yearsLabel;
	private JSpinner yearsSpinner;
	private JLabel monthsLabel;
	private JComboBox monthsComboBox;
	private JPanel yearMonthPanel;
	private JTable daysTable;
	private AbstractTableModel daysModel;
	private Calendar calendar;

	private int day, maxDay, month, year;// from 0 not from 1
	private int nowday, nowmonth, nowyear;
	private String date;

	private AixzSensor sensor;

	public AixzCalendar() {
		cPane = this;// (JPanel) getContentPane();
		cPane.setLayout(new BorderLayout());
		sensor = new AixzSensor(this);
		calendar = Calendar.getInstance();
		init();
	}

	private void init() {
		initYearsSpinner();
		initMonthsComboBox();
		initDaysTable();
	}

	private void initYearsSpinner() {

		// yearsLabel yearsSpinner
		yearsLabel = new JLabel("Year: ");
		yearsSpinner = new JSpinner();
		yearsSpinner.setEditor(new JSpinner.NumberEditor(yearsSpinner, "0000"));
		nowday = calendar.get(Calendar.DAY_OF_MONTH);
		nowyear = year = calendar.get(Calendar.YEAR);
		yearsSpinner.setValue(nowyear);
		yearsSpinner.addChangeListener(new ChangeListener() {// listener
					public void stateChanged(ChangeEvent changeEvent) {
						day = calendar.get(Calendar.DAY_OF_MONTH);
						calendar.set(Calendar.DAY_OF_MONTH, 1);
						year = ((Integer) yearsSpinner.getValue()).intValue();
						calendar.set(Calendar.YEAR, year);
						maxDay = calendar
								.getActualMaximum(Calendar.DAY_OF_MONTH);
						calendar.set(Calendar.DAY_OF_MONTH,
								day > maxDay ? maxDay : day);
						updateView();
						date = String.valueOf(year)
								+ new DecimalFormat("00").format(month + 1)// String.valueOf(month+1)
								+ new DecimalFormat("00").format(day);
						sensor.setData(date);//
						sensor.notifyObservers();//
					}
				});
		// yearMonthPanel(new JPanel, yearPanel(yearsLabel,yearsSpinner) )
		yearMonthPanel = new JPanel();
		cPane.add(yearMonthPanel, BorderLayout.NORTH);
		yearMonthPanel.setLayout(new BorderLayout());
		yearMonthPanel.add(new JPanel(), BorderLayout.CENTER);
		JPanel yearPanel = new JPanel();
		yearMonthPanel.add(yearPanel, BorderLayout.WEST);
		yearPanel.setLayout(new BorderLayout());
		yearPanel.add(yearsLabel, BorderLayout.WEST);
		yearPanel.add(yearsSpinner, BorderLayout.CENTER);
	}

	private void initMonthsComboBox() {
		// monthPanel(monthsLabel,monthsComboBox)
		monthsLabel = new JLabel("Month: ");
		monthsComboBox = new JComboBox();
		for (int i = 1; i <= 12; i++) {
			monthsComboBox.addItem(i);// new Integer(i)
		}
		nowmonth = month = calendar.get(Calendar.MONTH);
		monthsComboBox.setSelectedIndex(nowmonth);
		monthsComboBox.addActionListener(new ActionListener() {// listener
					public void actionPerformed(ActionEvent actionEvent) {
						day = calendar.get(Calendar.DAY_OF_MONTH);
						calendar.set(Calendar.DAY_OF_MONTH, 1);
						month = monthsComboBox.getSelectedIndex();
						calendar.set(Calendar.MONTH, month);
						maxDay = calendar
								.getActualMaximum(Calendar.DAY_OF_MONTH);
						calendar.set(Calendar.DAY_OF_MONTH,
								day > maxDay ? maxDay : day);
						updateView();
						date = String.valueOf(year)
								+ new DecimalFormat("00").format(month + 1)// String.valueOf(month+1)
								+ new DecimalFormat("00").format(day);
						sensor.setData(date);//
						sensor.notifyObservers();//
					}
				});
		JPanel monthPanel = new JPanel();
		yearMonthPanel.add(monthPanel, BorderLayout.EAST);
		monthPanel.setLayout(new BorderLayout());
		monthPanel.add(monthsLabel, BorderLayout.WEST);
		monthPanel.add(monthsComboBox, BorderLayout.CENTER);
	}// init monthsComboBox

	private void initDaysTable() {
		// daysModel daysTable
		daysModel = new DaysModel();

		daysTable = new CalendarTable(daysModel, calendar);
		daysTable.setCellSelectionEnabled(true);
		daysTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

		daysTable.setDefaultRenderer(daysTable.getColumnClass(0),
				new MyTableCellRenderer());
		updateView();
		daysTable.addMouseListener(new MouseAdapter() {// listener
					public void mouseClicked(MouseEvent e) {
						int row = daysTable.getSelectedRow();
						int col = daysTable.getSelectedColumn();
						if (row == 0)
							return;
						Object value = daysTable.getValueAt(row, col);
						if (value == null) {
							date = String.valueOf(nowyear)
									+ new DecimalFormat("00")
											.format(nowmonth + 1)
									+ new DecimalFormat("00").format(nowday);
							yearsSpinner.setValue(nowyear);
							monthsComboBox.setSelectedIndex(nowmonth);
						} else
							date = String.valueOf(year)
									+ new DecimalFormat("00").format(month + 1)// String.valueOf(month+1)
									+ new DecimalFormat("00").format(value);
						sensor.setData(date);
						sensor.notifyObservers();
					}
				});

		cPane.add(daysTable, BorderLayout.CENTER);
		date = String.valueOf(nowyear)
				+ new DecimalFormat("00").format(nowmonth + 1)
				+ new DecimalFormat("00").format(nowday);
		sensor.setData(date);
	}

	public static String getHeader(int index) {
		switch (index) {
		case 0:
			return WEEK_SUN;
		case 1:
			return WEEK_MON;
		case 2:
			return WEEK_TUE;
		case 3:
			return WEEK_WED;
		case 4:
			return WEEK_THU;
		case 5:
			return WEEK_FRI;
		case 6:
			return WEEK_SAT;
		default:
			return null;
		}
	}

	public void updateView() {
		daysModel.fireTableDataChanged();
		daysTable.setRowSelectionInterval(calendar.get(Calendar.WEEK_OF_MONTH),
				calendar.get(Calendar.WEEK_OF_MONTH));
		daysTable.setColumnSelectionInterval(
				calendar.get(Calendar.DAY_OF_WEEK) - 1, calendar
						.get(Calendar.DAY_OF_WEEK) - 1);
	}

	public String getDate() {
		return date;
	}

	public AixzSensor getSensor() {
		return sensor;
	}

	public class MyTableCellRenderer implements TableCellRenderer {
		public Component getTableCellRendererComponent(JTable table,
				Object value, boolean isSelected, boolean hasFocus, int row,
				int column) {
			String text = (value == null) ? "" : value.toString();
			JLabel cell = new JLabel(text);// Label
			cell.setOpaque(true);
			if (row == 0) {
				cell.setForeground(headerForeground);
				cell.setBackground(headerBackground);
			} else {
				cell.setToolTipText("单击查看当日事务");
				if (isSelected) {
					cell.setForeground(selectedForeground);
					cell.setBackground(selectedBackground);
				} else {
					cell.setForeground(foreground);
					cell.setBackground(background);
				}
			}

			return cell;
		}// end getTableCellRendererComponent
	}// end class TableCellRenderer

	public class DaysModel extends AbstractTableModel {
		public int getRowCount() {
			return 7; // 加上头部共7行
		}

		public int getColumnCount() {
			return 7;
		}

		public Object getValueAt(int row, int column) {
			if (row == 0) {
				return getHeader(column);
			}
			row--;
			Calendar calendar = (Calendar) AixzCalendar.this.calendar.clone();
			calendar.set(Calendar.DAY_OF_MONTH, 1);
			int dayCount = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
			int moreDayCount = calendar.get(Calendar.DAY_OF_WEEK) - 1;
			int index = row * 7 + column;
			int dayIndex = index - moreDayCount + 1;
			if (index < moreDayCount || dayIndex > dayCount) {
				return null;
			} else {
				return new Integer(dayIndex);
			}
		}
	}// end class DaysModel

	public class CalendarTable extends JTable {

		private Calendar calendar;

		public CalendarTable(TableModel model, Calendar calendar) {
			super(model);
			this.calendar = calendar;
		}

		public void changeSelection(int row, int column, boolean toggle,
				boolean extend) {
			super.changeSelection(row, column, toggle, extend);
			if (row == 0) {
				return;
			}
			Object obj = getValueAt(row, column);
			if (obj != null) {
				calendar.set(Calendar.DAY_OF_MONTH, ((Integer) obj).intValue());
			}// click the null return select nowday
			else
				calendar.set(Calendar.DAY_OF_MONTH, nowday);
		}

	}// end class CalendarTable

	public static void main(String[] args) {
		JFrame frame = new JFrame("Calendar Application");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		AixzCalendar calendar = new AixzCalendar();
		calendar.init();
		frame.getContentPane().add(calendar);
		frame.setSize(240, 172);
		frame.setVisible(true);
	}

}
